home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue29 / construc / INDEXBOB.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-11-27  |  5.1 KB  |  207 lines

  1. unit IndexBob;
  2. {$I-}
  3. interface
  4. const
  5.   MaxPage = 255;
  6.  
  7. type
  8.   TNumPage = 0..MaxPage; { max number of webpages in site }
  9.   TURLPage = ShortString { assuming URL <= 255 characters };
  10.  
  11. var
  12.   WebPages: TNumPage = 0;
  13.   WebPage: Array[TNumPage] of TURLPage;
  14.  
  15. const
  16.   MaxKeyword = 31;
  17.  
  18. type
  19.   TKeyword = String[MaxKeyword];
  20.   TPageSet = Set of TNumPage;
  21.  
  22.   function Pages(PageSet: TPageSet): Byte;
  23.  
  24. type
  25.   TNode = record
  26.     Keyword: TKeyword; { 32 bytes }
  27.     URLs: TPageSet;    { 32 bytes }
  28.   end {TNode};
  29.  
  30.   TTree = class
  31.     Node: TNode;
  32.     constructor Create;
  33.     destructor Destroy; override;
  34.     function FindKeywordInPages(const KeyWord: TKeyword): TPageSet;
  35.   private
  36.     Prev,Next: TTree;
  37.   end {TTree};
  38.  
  39. var
  40.   Keywords: Integer = 0;
  41.   root: TTree = nil;
  42.  
  43. type
  44.   TIndexFile = File of TNode;
  45.  
  46. implementation
  47.  
  48.   function Pages(PageSet: TPageSet): Byte;
  49.   var
  50.     B: Byte;
  51.   begin
  52.     Result := 0;
  53.     for B := 0 to MaxPage do
  54.       if B in PageSet then Result := Result + 1
  55.   end {Pages};
  56.  
  57.   constructor TTree.Create;
  58.   begin
  59.     inherited Create;
  60.     Prev := nil;
  61.     Next := nil;
  62.   {$IFDEF NULL}
  63.     FillChar(Node.Keyword,MaxKeyword+1,#0); { sparse }
  64.     Node.URLs := []
  65.   {$ENDIF}
  66.   end {Create};
  67.  
  68.   destructor TTree.Destroy;
  69.   begin
  70.     if Prev <> nil then Prev.Free;
  71.     if Next <> nil then Next.Free;
  72.     inherited Destroy
  73.   end {Destroy};
  74.  
  75.   function TTree.FindKeywordInPages(const Keyword: TKeyword): TPageSet;
  76.   var
  77.     tmp: TTree;
  78.   begin
  79.     Result := [];
  80.     tmp := root;
  81.     repeat
  82.       if tmp.Node.Keyword > Keyword then
  83.         tmp := tmp.Prev
  84.       else
  85.         if tmp.Node.Keyword < Keyword then
  86.           tmp := tmp.Next
  87.     until (tmp = nil) or (tmp.Node.Keyword = Keyword);
  88.     if tmp <> nil then
  89.       Result := tmp.Node.URLs
  90.   end {FindKeywordInPages};
  91.  
  92.  
  93.   function CreateRoot(depth: Integer): TTree;
  94.   var
  95.     r: TTree;
  96.   begin
  97.     if depth > 0 then
  98.     begin
  99.       r := TTree.Create;
  100.       r.Prev := CreateRoot(depth-1);
  101.       r.Next := CreateRoot(depth-1);
  102.       CreateRoot := r
  103.     end
  104.     else CreateRoot := nil
  105.   end {CreateRoot};
  106.  
  107.   procedure CreateLeafs(var number: Integer; root: TTree);
  108.   begin
  109.     if root.Prev <> nil then
  110.     begin
  111.       CreateLeafs(number,root.Prev);
  112.       if number > 0 then CreateLeafs(number,root.Next)
  113.     end
  114.     else
  115.     begin
  116.       root.Prev := TTree.Create;
  117.       Dec(number);
  118.       if number > 0 then
  119.       begin
  120.         root.Next := TTree.Create;
  121.         Dec(number)
  122.       end
  123.     end
  124.   end {CreateLeafs};
  125.  
  126.   procedure ReadNode(var IndexFile: TIndexFile; root: TTree);
  127.   begin
  128.     if root.Prev <> nil then ReadNode(IndexFile, root.Prev);
  129.     read(IndexFile,root.Node);
  130.     Inc(Keywords);
  131.     if root.Next <> nil then ReadNode(IndexFile, root.Next)
  132.   end {ReadNode};
  133.  
  134. var
  135.   PageFile: Text;
  136.   IndexFile: TIndexFile;
  137.   total,depth,i: Integer;
  138.  
  139. initialization
  140.   writeln('content-type: text/html');
  141.   writeln;
  142.   writeln('<HTML>');
  143.   writeln('<BODY BACKGROUND="/gif/back.gif">');
  144.   writeln('<H2>IndexBob</H2>');
  145.   writeln('IndexBob is my Website Search Engine, entirely written in Borland Delphi (the source code even compiles with Delphi 2).');
  146.   writeln('The search engine is topic of a 2-part <I>Under Construction</I> column in the Jan/Feb issues of The Delphi Magazine.');
  147.   writeln('<BR>');
  148.   writeln('Ultimately, the search engine should support multiple keyword search, combined with <B>AND</B>, <B>OR</B> and <B>NOT</B> abilities.');
  149.   writeln('For now, you can only search for a single keyword, however...');
  150.   writeln('<P>');
  151.   writeln('<FORM METHOD="POST" ACTION="/cgi-bin/indexbob.exe">');
  152.   writeln('<TABLE>');
  153.   writeln('<TR><TD><I>Search again:</I></TD>');
  154.   writeln('<TD><INPUT TYPE="TEXT" NAME="Keyword" SIZE=29></TD></TR>');
  155.   writeln('<TR><TD></TD><TD>');
  156.   writeln('<INPUT TYPE="SUBMIT" VALUE="Search">');
  157.   writeln('<INPUT TYPE="RESET" VALUE="Reset"></TD></TR>');
  158.   writeln('</TABLE>');
  159.   writeln('</FORM>');
  160.   writeln('Feedback is welcome in my newsgroup <A HREF="news://news.shoresoft.com/drbob.internet.tools">drbob.internet.tools</A>.');
  161.   writeln('<HR>');
  162.   assign(PageFile,'pages.bob');
  163.   reset(PageFile);
  164.   if IOResult = 0 then
  165.   begin
  166.     while not eof(PageFile) do
  167.     begin
  168.       readln(PageFile,WebPage[WebPages]);
  169.       Inc(WebPages)
  170.     end;
  171.     close(PageFile)
  172.   end;
  173.   assign(IndexFile,'index.bob');
  174.   reset(IndexFile);
  175.   total := FileSize(IndexFile);
  176.   if IOResult = 0 then
  177.   begin
  178.     if total = 1 then root := TTree.Create
  179.     else {total > 1}
  180.     begin
  181.       depth := 0;
  182.       i := 1;
  183.       repeat
  184.         i := i SHL 1;
  185.         Inc(depth)
  186.       until i >= total;
  187.       Dec(depth);
  188.       i := total - (i SHR 1) + 1;
  189.       root := CreateRoot(depth);
  190.       if i > 0 then CreateLeafs(i, root)
  191.     end;
  192.     if total > 0 then
  193.       ReadNode(IndexFile, root);
  194.     close(IndexFile)
  195.   end
  196. finalization
  197.   writeln('<HR>');
  198.   writeln('<FONT SIZE=1>');
  199.   writeln('Webpages: ',WebPages);
  200.   writeln('<BR>Keywords: ',Keywords);
  201.   writeln('</FONT>');
  202.   writeln('<HR>');
  203.   writeln('</BODY>');
  204.   writeln('</HTML>');
  205.   root.Free
  206. end.
  207.